package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.OrdersCancelDTO;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersRejectionDTO;
import com.sky.dto.OrdersSubmitDTO;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.AddressBookService;
import com.sky.service.OrderService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.support.GroovyWebApplicationContext;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 苏成博
 * @date 2023-02-13 10:45
 */
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AddressBookMapper addressBookMapper;
    @Autowired
    private ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private WorkspaceService workspaceService;
    @Autowired
    private AddressBookService addressBookService;
    /**
     * 用户新增订单方法
     * @param ordersSubmitDTO
     * @return
     */
    @Transactional
    public OrderSubmitVO addOrder(OrdersSubmitDTO ordersSubmitDTO) {
        Long userId = BaseContext.getCurrentId();//获取当前用户id
        //根据前端传递的地址ID数据查询出地址信息
        AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
        if (addressBook == null) {
            throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
        }
        //判断地址是否在指定距离内
        addressBookService.judgeDistance(addressBook);
        //查出此用户的购物车数据
        List<ShoppingCart> cartList = shoppingCartMapper.findShoppingCartByUserId(userId);
        if (cartList == null || cartList.size() == 0) {
            throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
        }
        Orders orders = new Orders();
        //用户订单号
        orders.setNumber(String.valueOf(System.currentTimeMillis()));
        BeanUtils.copyProperties(ordersSubmitDTO, orders);
        orders.setStatus(Orders.PENDING_PAYMENT);//下单状态
        orders.setUserId(userId);//下单用户id
        orders.setOrderTime(LocalDateTime.now());
        //结账时间
        orders.setPayStatus(Orders.UN_PAID);//用户支付方式
        //根据用户Id查询用户
        User user = userMapper.getById(userId);
        orders.setUserName(user.getName());//设置用户名

        //设置收货信息
        orders.setPhone(addressBook.getPhone());
        //设置收货地址
        orders.setAddress(addressBook.getProvinceName() + addressBook.getCityName() + addressBook.getDistrictName() + "  " + addressBook.getDetail());
        //设置收货人
        orders.setConsignee(addressBook.getConsignee());
        //添加订单数据
        orderMapper.addOrder(orders);
        //创建订单详情数据
        //将购物车中的数据封装到详情表里面去
        ArrayList<OrderDetail> ordersDetailList = new ArrayList<>();
        OrderDetail orderDetail;
        ShoppingCart shoppingCart;
        for (int i = 0; i < cartList.size(); i++) {
            orderDetail = new OrderDetail();
            shoppingCart = cartList.get(i);
            orderDetail.setAmount(shoppingCart.getAmount());
            orderDetail.setName(shoppingCart.getName());
            orderDetail.setDishFlavor(shoppingCart.getDishFlavor());
            orderDetail.setOrderId(orders.getId());
            orderDetail.setDishId(shoppingCart.getDishId());
            orderDetail.setSetmealId(shoppingCart.getSetmealId());
            orderDetail.setNumber(shoppingCart.getNumber());
            orderDetail.setImage(shoppingCart.getImage());
            ordersDetailList.add(orderDetail);
        }
        //向订单详情表中添加N条数据
        orderDetailMapper.addOrderDetail(ordersDetailList);
        //清理购物车中的数据
        shoppingCartMapper.deleteAll(userId);
        //返回封装信息
        OrderSubmitVO orderSubmitVO = OrderSubmitVO.builder()
                .id(orders.getId())
                .orderNumber(orders.getNumber())
                .orderTime(orders.getOrderTime())
                .orderAmount(orders.getAmount())
                .build();
        return orderSubmitVO;
    }

    /**
     * 历史订单查询
     *
     * @param ordersPageQueryDTO
     * @return
     */
    public PageResult findHistoryOrders(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        Page<OrderVO> page = orderMapper.findHistoryOrders(ordersPageQueryDTO);
        List<OrderVO> result = page.getResult();
        OrderVO orderVO;
        List<OrderDetail> detailList;
        for (int i = 0; i < result.size(); i++) {
            orderVO = result.get(i);
            detailList = orderDetailMapper.findOrderDetailByOrderId(orderVO.getId());
            orderVO.setOrderDetailList(detailList);
        }
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 查询订单
     *
     * @param id
     * @return
     */
    @Override
    public OrderVO findOrdersById(Long id) {
        OrderVO orderVO = orderMapper.findOrdersById(id);
        return orderVO;
    }

    /**
     * 根据订单id取消订单
     *
     * @param id
     */
    public void cancelOrder(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setCancelTime(LocalDateTime.now());
        orders.setStatus(Orders.CANCELLED);
        orderMapper.updateOrder(orders);
    }

    @Override
    public void repetitionOrder(Long id) {
        //根据订单id查询出订单和订单详情数据
        OrderVO ordersVO = orderMapper.findOrdersById(id);
        //先封装一个订单对象
        ShoppingCart shoppingCart;
        List<OrderDetail> orderDetailList = ordersVO.getOrderDetailList();
        for (int i = 0; i < orderDetailList.size(); i++) {
            shoppingCart = new ShoppingCart();
            BeanUtils.copyProperties(orderDetailList.get(i), shoppingCart);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCart.setUserId(BaseContext.getCurrentId());
            shoppingCartMapper.saveShoppinCart(shoppingCart);
        }
    }

    @Override
    public void acceptOrder(Long id) {
        Orders orders = Orders.builder().id(id).status(Orders.CONFIRMED).build();
        orderMapper.updateOrder(orders);
    }

    @Override
    public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
        PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
        Long currentId = BaseContext.getCurrentId();
        ordersPageQueryDTO.setUserId(currentId);
        Page<OrderVO> orderVOPage = orderMapper.findHistoryOrders(ordersPageQueryDTO);
        List<OrderDetail> orderDetailList;
        OrderVO orderVO;
        for (int i = 0; i < orderVOPage.size(); i++) {
            orderVO = orderVOPage.get(i);
            orderDetailList = orderDetailMapper.findOrderDetailByOrderId(orderVO.getId());
            String orderDishesName = " / ";
            for (int j = 0; j < orderDetailList.size(); j++) {
                orderDishesName = orderDishesName + orderDetailList.get(j).getName() + " / ";
            }
            orderVO.setOrderDishes(orderDishesName);
        }
        return new PageResult(orderVOPage.getTotal(), orderVOPage.getResult());
    }

    @Override
    public OrderStatisticsVO statisticsOrders() {
        List<BusinessVO> businessVOs = orderMapper.statisticsOrders();
        OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
        Integer status;
        Integer count;
        for (BusinessVO businessVO : businessVOs) {
            status = businessVO.getStatus();
            count = businessVO.getCount();
            if (status == Orders.TO_BE_CONFIRMED) {
                orderStatisticsVO.setToBeConfirmed(count);
            }
            if (status == Orders.CONFIRMED) {
                orderStatisticsVO.setConfirmed(count);
            }
            if (status == Orders.DELIVERY_IN_PROGRESS) {
                orderStatisticsVO.setDeliveryInProgress(count);
            }
        }
        return orderStatisticsVO;
    }

    @Override
    public void cancelOrders(OrdersCancelDTO ordersCancelDTO) {
        Orders orders = new Orders();
        orders.setId(ordersCancelDTO.getId());
        orders.setCancelReason(ordersCancelDTO.getCancelReason());
        orders.setCancelTime(LocalDateTime.now());
        orders.setPayStatus(Orders.REFUND);
        orders.setStatus(Orders.CANCELLED);
        orders.setAmount(new BigDecimal(0));
        orderMapper.updateOrder(orders);
    }

    @Override
    public void completeOrders(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.COMPLETED);
        orderMapper.updateOrder(orders);
    }

    @Override
    public void rejectionOrders(OrdersRejectionDTO ordersRejectionDTO) {
        Orders orders = new Orders();
        orders.setId(ordersRejectionDTO.getId());
        orders.setCancelReason(ordersRejectionDTO.getRejectionReason());
        orders.setCancelTime(LocalDateTime.now());
        orders.setPayStatus(Orders.REFUND);
        orders.setStatus(Orders.CANCELLED);
        orders.setAmount(new BigDecimal(0));
        orderMapper.updateOrder(orders);
    }

    @Override
    public void deliveryOrder(Long id) {
        Orders orders = new Orders();
        orders.setId(id);
        orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
        orderMapper.updateOrder(orders);
    }

    @Override
    public TurnoverReportVO getTurnoverData(LocalDate begin, LocalDate end) {
        //获取begin和end之间差的天数
        List<LocalDate> dateList = new ArrayList<>();
        while (!begin.isEqual(end)) {
            dateList.add(begin);
            begin = begin.plusDays(1);
        }
        dateList.add(end);
        //封装turnoverList，获取日期内已完成的订单的收入
        LocalDateTime localDateTimeMin;
        LocalDateTime localDateTimeMax;
        Double amount;
        Map<String, Object> map = new HashMap<>();
        ArrayList<Double> turnoverList = new ArrayList<>();
        for (LocalDate localDate : dateList) {
            localDateTimeMin = localDate.atTime(LocalTime.MIN);
            localDateTimeMax = localDate.atTime(LocalTime.MAX);
            map.put("begin", localDateTimeMin);
            map.put("end", localDateTimeMax);
            map.put("status", Orders.COMPLETED);
            //select count(amount) from orders where order_time between begin and end  and status = 5;
            amount = orderMapper.getTurnoverData(map);
            amount = amount == null ? 0 : amount;
            turnoverList.add(amount);
        }
        return new TurnoverReportVO(
                StringUtils.join(dateList, ","),
                StringUtils.join(turnoverList, ","));
    }

    @Override
    public OrderReportVO getOrderReportVO(LocalDate begin, LocalDate end) {
        //获取begin和end之间差的天数
        List<LocalDate> dateList = new ArrayList<>();
        while (!begin.isEqual(end)) {
            dateList.add(begin);
            begin = begin.plusDays(1);
        }
        dateList.add(end);
        //每日有效订单数 select count(id) from orders where order_time between minTIme and maxTime and status=completed
        List<Integer> validOrdersList = new ArrayList<>();
        //封装每日订单数 select count(id) from orders where order_time between minTIme and maxTime
        List<Integer> totalOrdersList = new ArrayList<>();
        Map<String, Object> map = new HashMap<>();
        Integer validOrders;
        Integer totalOrders;
        for (LocalDate localDate : dateList) {
            map.put("begin", localDate.atTime(LocalTime.MIN));
            map.put("end", localDate.atTime(LocalTime.MAX));
            map.put("status", Orders.COMPLETED);
            //封装每日有效订单
            validOrders = orderMapper.findCompletedOrders(map);
            validOrders = validOrders == null ? 0 : validOrders;
            validOrdersList.add(validOrders);
            //封装每日订单总数
            totalOrders = orderMapper.findTotalOrders(map);
            totalOrders = totalOrders == null ? 0 : totalOrders;
            totalOrdersList.add(totalOrders);
        }
        //封装订单总数
        Double countAllOrders = orderMapper.findAllTotalOrders();
        //封装有效订单数
        Double allValidOrders = orderMapper.findAllValidOrders(Orders.COMPLETED);
        //计算订单完成率
        Double orderCompletionRate = allValidOrders / countAllOrders;
        return new OrderReportVO(
                StringUtils.join(dateList, ","),
                StringUtils.join(totalOrdersList, ","),
                StringUtils.join(validOrdersList, ","),
                countAllOrders.intValue(),
                allValidOrders.intValue(),
                orderCompletionRate
        );
    }

    /**
     * 查出销量排名前十的商品
     *
     * @param begin
     * @param end
     * @return
     */
    public SalesTop10ReportVO getSalesTop10ReportVO(LocalDate begin, LocalDate end) {
        List<Top10Sales> top10SalesList = orderMapper.getSalesTop10ReportVO(begin, end);
        //封装商品名称列表
        ArrayList<String> nameList=new ArrayList<>();
        //封装销量列表
        ArrayList<Integer> numberList=new ArrayList<>();
        for (Top10Sales top10Sales : top10SalesList) {
            nameList.add(top10Sales.getName());
            numberList.add(top10Sales.getNumber());
        }
        return new SalesTop10ReportVO(
                StringUtils.join(nameList,","),
                StringUtils.join(numberList,",")
        );
    }

    @Override
    public void exportBusinessData(HttpServletResponse httpServletResponse) {
        LocalDate nowDate = LocalDate.now();
        LocalDate localDate = nowDate.minusDays(30);
        LocalDateTime dateTimeMin = localDate.atTime(LocalTime.MIN);
        LocalDateTime dateTimeMax = nowDate.minusDays(1).atTime(LocalTime.MAX);
        BusinessDataVO businessData = workspaceService.getTodayBusinessData(dateTimeMin,dateTimeMax);
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
        try {
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(inputStream);
            XSSFSheet sheet1 = xssfWorkbook.getSheet("Sheet1");
            XSSFRow row2 = sheet1.getRow(1);
            row2.getCell(1).setCellValue(localDate.toString()+"至"+nowDate.minusDays(1).toString());
            XSSFRow row4 = sheet1.getRow(3);
            row4.getCell(2).setCellValue(businessData.getTurnover());
            row4.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row4.getCell(6).setCellValue(businessData.getNewUsers());
            XSSFRow row5 = sheet1.getRow(4);
            row5.getCell(2).setCellValue(businessData.getValidOrderCount());
            row5.getCell(4).setCellValue(businessData.getUnitPrice());
            for (int i = 0; i < 30; i++) {
                localDate=localDate.plusDays(i);
                workspaceService.getTodayBusinessData(LocalDateTime.of(localDate,LocalTime.MIN),LocalDateTime.of(localDate,LocalTime.MAX));
                XSSFRow row = sheet1.getRow(7 + i);
                row.getCell(1).setCellValue(localDate.toString());
                row.getCell(2).setCellValue(businessData.getTurnover());
                row.getCell(3).setCellValue(businessData.getValidOrderCount());
                row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessData.getUnitPrice());
                row.getCell(6).setCellValue(businessData.getNewUsers());
            }
            ServletOutputStream outputStream = httpServletResponse.getOutputStream();
            //输出到浏览器
            xssfWorkbook.write(outputStream);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
